package de.dhbwstuttgart.vincon.telefoncompany.utils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;

import com.db4o.ObjectContainer;

import de.dhbwstuttgart.vincon.telefoncompany.model.Call;
import de.dhbwstuttgart.vincon.telefoncompany.model.Customer;
import de.dhbwstuttgart.vincon.telefoncompany.model.Phone;

public class DataCreatorDb4o {

	private static final int MONTH_QUANTITY = 12;
	private static final int CALLEE_QUANTITY = 1;
	private static final int CALL_QUANTITY = 3;
	private static final int CUSTOMER_QUANTITY = 100;

	private TextReader forename;
	private TextReader surname;
	private TextReader dailingcode;

	private ArrayList<Customer> customerList;
	private HashSet<Customer> calleeList;

	public DataCreatorDb4o() {
		forename = new TextReader("forename.txt");
		surname = new TextReader("surname.txt");
		dailingcode = new TextReader("dailingcode.txt");
	}

	public void createData(int factor, ObjectContainer db) {
		customerList = new ArrayList<Customer>();
		calleeList = new HashSet<Customer>();

		int specialCustomer = 0;
		Customer customer;
		int phoneQuantity = 0;

		// create customers with their phones
		for (int i = 0; i < CUSTOMER_QUANTITY * factor; i++) {
			if (specialCustomer == 0) {
				specialCustomer = (int) (Math.random() * 10);

				if (specialCustomer == 10
						|| i == CUSTOMER_QUANTITY * factor - 1) {
					customer = addSpecialCustomer();
				} else {
					customer = addCustomer();
					specialCustomer = 0;
				}
			} else {
				customer = addCustomer();
			}

			addPhone(customer);

			phoneQuantity++;
			if (phoneQuantity == 2) {
				addPhone(customer);
				phoneQuantity = 0;
			}

			db.store(customer);
		}

		db.commit();
		// System.out.println("Saved all customers and phones in the database");

		Customer callee;
		// create calls for each month
		for (int month = 0; month < MONTH_QUANTITY; month++) {

			for (Customer caller : customerList) {

				// create the callees for each caller
				do {
					callee = getRandomCustomer();
					calleeList.add(callee);
				} while (caller.equals(callee)
						&& calleeList.size() < CALLEE_QUANTITY * factor);

				for (int calls = 0; calls < CALL_QUANTITY * factor; calls++) {
					callee = getRandomCallee();
					db.store(createCall(caller.getRandomPhone(),
							callee.getRandomPhone(), month));
				}

				calleeList.clear();
				
				db.commit();
			}
			
			// System.out.println("Saved all calls for the " + month +
			// " month in the database");

		}

		calleeList = null;
	}

	private Customer addCustomer() {
		Customer customer = new Customer(forename.getRandomData(),
				surname.getRandomData());
		customerList.add(customer);
		return customer;
	}

	private Customer addSpecialCustomer() {
		Customer customer = new Customer("Max", "Mustermann");
		customerList.add(customer);
		return customer;
	}

	private Phone addPhone(Customer customer) {
		String number = dailingcode.getRandomData() + "/"
				+ (int) (Math.random() * 999999 + 1000);
		Phone phone = new Phone(number, customer);
		customer.addPhone(phone);
		return phone;
	}

	private Customer getRandomCallee() {
		return (Customer) calleeList.toArray()[(int) (Math.random() * calleeList
				.size())];
	}

	private Customer getRandomCustomer() {
		return customerList.get((int) (Math.random() * customerList.size()));
	}

	private Call createCall(Phone caller, Phone callee, int month) {
		int year = 2012;
		int dayOfMonth = (int) (Math.random() * 25);

		int hourOfDay1 = (int) (Math.random() * 24);
		int minute1 = (int) (Math.random() * 60);
		int second1 = (int) (Math.random() * 60);

		int hourOfDay2 = (int) (Math.random() * 24);
		int minute2 = (int) (Math.random() * 60);
		int second2 = (int) (Math.random() * 60);

		Calendar time1 = new GregorianCalendar();
		time1.set(Calendar.YEAR, year);
		time1.set(Calendar.MONTH, month);
		time1.set(Calendar.DAY_OF_MONTH, dayOfMonth);
		time1.set(Calendar.HOUR_OF_DAY, hourOfDay1);
		time1.set(Calendar.MINUTE, minute1);
		time1.set(Calendar.MINUTE, second1);
		Calendar time2 = new GregorianCalendar();
		time2.set(Calendar.YEAR, year);
		time2.set(Calendar.MONTH, month);
		time2.set(Calendar.DAY_OF_MONTH, dayOfMonth);
		time2.set(Calendar.HOUR_OF_DAY, hourOfDay2);
		time2.set(Calendar.MINUTE, minute2);
		time2.set(Calendar.MINUTE, second2);

		Call call;

		if (time1.before(time2)) {
			call = new Call(time1, time2, caller, callee);
		} else {
			call = new Call(time2, time1, caller, callee);
		}

		return call;
	}
}
